using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using Microsoft.SharedSource.SqlServer.MDDE.Repository;
using System.Collections;
using System.Xml;
using Microsoft.SharedSource.SqlServer.MDDE.Middleware;

namespace Microsoft.SharedSource.SqlServer.MDDE.ManagementStudio
{
    public partial class MainForm : Form
    {
        #region Fields

        Dictionary<string, XmlDocument> repositories =
            new Dictionary<string, XmlDocument>();

        #endregion

        #region Constructor

        public MainForm()
        {
            InitializeComponent();
        }

        #endregion

        #region Event Handlers

        private void btnConnect_Click(object sender, EventArgs e)
        {
            ConnectToRepository();
        }

        private void connectToolStripMenuItem_Click(
            object sender, EventArgs e)
        {
            ConnectToRepository();
        }

        private void btnDisconnect_Click(object sender, EventArgs e)
        {
            if (trvExplorer.SelectedNode != null)
            {
                if (trvExplorer.SelectedNode.Level == 0)
                {
                    string repositoryIdentifier = trvExplorer.SelectedNode.Text;
                    trvExplorer.Nodes.RemoveByKey(repositoryIdentifier);
                }
                else
                {
                    int countLevel = trvExplorer.SelectedNode.Level;
                    while (countLevel > 0)
                    {
                        string repositoryIdentifierChild = (trvExplorer.SelectedNode.Parent).Text;
                        trvExplorer.SelectedNode = trvExplorer.SelectedNode.Parent;
                        countLevel--;
                        trvExplorer.Nodes.RemoveByKey(repositoryIdentifierChild);
                    }
                }
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;

            // Pick out the connection string.  
            string repositoryConnectionString =
            ((XmlNode)trvExplorer.SelectedNode.Tag).OwnerDocument.
            FirstChild.Attributes["ConnectionString"].Value;

            // Pick out the selected node.
            XmlNode selectedXmlNode = (XmlNode)trvExplorer.SelectedNode.Tag;

            XmlDocument repositoryTree = MDDEManager.GetRepositoryTreeForSelectedNode
                (repositoryConnectionString, selectedXmlNode);

            RefreshRepositoryForSelectedNode(repositoryTree);
            this.Cursor = Cursors.Default;
        }

        private void createInstanceToolStripMenuItem_Click(
            object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;
            string templateName =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                Attributes["Name"].Value;

            CreateInstance createInstance =
                new CreateInstance(repositoryConnectionString, templateName);

            createInstance.ShowDialog();

            // Pick out the selected node.
            XmlNode selectedXmlNode = ((XmlNode)((ToolStripMenuItem)sender).Tag).
                SelectSingleNode("./Node[@Type=\"TemplateInstances\"]");

            // Refresh the repository tree.
            XmlDocument repositoryTree =
                MDDEManager.GetRepositoryTreeForSelectedNode(
                repositoryConnectionString, selectedXmlNode);

            RefreshRepositoryForSelectedNode(repositoryTree);
        }

        void createInstanceUsingWizard_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                Attributes["Name"].Value;

            InstanceCreator creator =
                new InstanceCreator(
                repositoryConnectionString, templateName);

            creator.ShowDialog();

            // Pick out the selected node.
            XmlNode selectedXmlNode = ((XmlNode)((ToolStripMenuItem)sender).Tag).
               SelectSingleNode("./Node[@Type=\"TemplateInstances\"]");

            // Refresh the repository tree.
            XmlDocument repositoryTree =
                MDDEManager.GetRepositoryTreeForSelectedNode(
                repositoryConnectionString, selectedXmlNode);

            RefreshRepositoryForSelectedNode(repositoryTree);
        }

        void deleteInstance_Click(object sender, EventArgs e)
        {
            // Pick out the tag.
            string[] instanceInfo = (string[])((ToolStripItem)sender).Tag;

            // Get the confirmation.
            DialogResult confirmation =
                MessageBox.Show(
                "Are you sure you want to delete template instance: " +
                instanceInfo[2] + "?", "Confirm Template Instance Delete",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (confirmation == DialogResult.No)
                return;

            // Delete the package.
            OperationResult result =
                MDDEManager.DeleteTemplateInstance(
                instanceInfo[0], instanceInfo[1], instanceInfo[2]);

            // Prepare message string.
            StringBuilder sb = new StringBuilder();
            foreach (string str in result.OperationLog)
                sb.Append(str);

            if (result.SuccessStatus)
            {
                // Refresh the repository tree.
                XmlDocument repositoryTree =
                    MDDEManager.GetRepositoryTree(
                    instanceInfo[0]);

                RefreshRepository(repositoryTree);
            }
            else
            {
                MessageBox.Show(
                    "Cannot delete template instance: " +
                    instanceInfo[2] + ".\n" +
                    sb.ToString(),
                    "Template Instance Deletion Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        void exportInstance_Click(object sender, EventArgs e)
        {
            // Pick out the tag.
            string[] instanceInfo = (string[])((ToolStripItem)sender).Tag;

            // Display the update template instance form.
            ExportInstance frmExport =
                new ExportInstance(
                instanceInfo[0], instanceInfo[1], instanceInfo[2]);

            frmExport.ShowDialog();
        }

        void updateInstance_Click(object sender, EventArgs e)
        {
            // Pick out the tag.
            string[] instanceInfo = (string[])((ToolStripItem)sender).Tag;

            // Display the update template instance form.
            UpdateTemplateInstance frmUpdate =
                new UpdateTemplateInstance(
                instanceInfo[0], instanceInfo[1], instanceInfo[2]);

            frmUpdate.ShowDialog();
        }

        void deleteTemplateMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName =
                ((XmlNode)((ToolStripItem)sender).Tag).
                Attributes["Name"].Value;

            // Get the confirmation.
            DialogResult confirmation =
                MessageBox.Show(
                "Are you sure you want to delete template: " +
                templateName + "?", "Confirm Template Delete",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (confirmation == DialogResult.No)
                return;

            // Delete the package.
            OperationResult result =
                MDDEManager.DeleteTemplate(
                repositoryConnectionString,
                templateName);

            // Prepare message string.
            StringBuilder sb = new StringBuilder();
            foreach (string str in result.OperationLog)
                sb.Append(str);

            if (result.SuccessStatus)
            {
                // Refresh the repository tree.
                XmlDocument repositoryTree =
                    MDDEManager.GetRepositoryTree(
                    repositoryConnectionString);

                RefreshRepository(repositoryTree);
            }
            else
            {
                MessageBox.Show(
                    "Cannot delete template: " + templateName + ".\n" +
                    sb.ToString(),
                    "Template Deletion Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        void updateTemplateMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName =
                ((XmlNode)((ToolStripItem)sender).Tag).
                Attributes["Name"].Value;

            UpdateTemplate updateTemplate =
                new UpdateTemplate(
                repositoryConnectionString, templateName);

            updateTemplate.ShowDialog();
        }

        void upgradeTemplateMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName =
                ((XmlNode)((ToolStripItem)sender).Tag).
                Attributes["Name"].Value;

            UpgradeTemplateWizardController upgradeTemplate =
                new UpgradeTemplateWizardController(
                repositoryConnectionString, templateName);

            upgradeTemplate.BeginWizardFlow();
        }


        void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName = ((XmlNode)((ToolStripItem)sender).Tag).
                ParentNode.ParentNode.Attributes["Name"].Value;

            string packageName =
                ((XmlNode)((ToolStripItem)sender).Tag).
                Attributes["Name"].Value;

            // Get the confirmation.
            DialogResult confirmation =
                MessageBox.Show(
                "Are you sure you want to delete package: " +
                packageName + "?", "Confirm Package Delete",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question);

            if (confirmation == DialogResult.No)
                return;

            // Delete the package.
            OperationResult result = MDDEManager.DeletePackage(
                repositoryConnectionString, templateName, packageName, null);

            // Prepare message string.
            StringBuilder sb = new StringBuilder();
            foreach (string str in result.OperationLog)
                sb.Append(str);

            if (result.SuccessStatus)
            {
                // Refresh the repository tree.
                XmlDocument repositoryTree =
                    MDDEManager.GetRepositoryTree(
                    repositoryConnectionString);

                RefreshRepository(repositoryTree);
            }
            else
            {
                MessageBox.Show(
                    "Cannot delete package: " + packageName + ".\n" +
                    sb.ToString(),
                    "Package Deletion Error",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            }
        }

        void exportPackageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            string templateName = ((XmlNode)((ToolStripItem)sender).Tag).
                ParentNode.ParentNode.Attributes["Name"].Value;

            string packageName =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                Attributes["Name"].Value;

            // Display the update template instance form.
            ExportPackage frmExport = new ExportPackage(
                repositoryConnectionString, templateName, packageName);

            frmExport.ShowDialog();
        }

        private void generatePackagesToolStripMenuItem_Click(
            object sender, EventArgs e)
        {
            // Get the repository connection string
            string repositoryConnectionString =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                OwnerDocument.FirstChild.
                Attributes["ConnectionString"].Value;

            // Get the template name.
            string templateName =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                Attributes["Name"].Value;

            GeneratePackages generatePackages =
                new GeneratePackages(
                repositoryConnectionString, templateName);

            generatePackages.ShowDialog();
        }

        void importPackageToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((ToolStripMenuItem)sender).Tag.ToString();

            ImportPackage importPackage =
                new ImportPackage(repositoryConnectionString);

            importPackage.ShowDialog();

            // Pick out the selected node.
            XmlNode selectedXmlNode = (XmlNode)trvExplorer.SelectedNode.Tag;

            // Refresh the repository tree.
            XmlDocument repositoryTree =
                MDDEManager.GetRepositoryTreeForSelectedNode(
                repositoryConnectionString, selectedXmlNode);
            RefreshRepositoryForSelectedNode(repositoryTree);
        }

        private void importTemplateToolStripMenuItem_Click(
            object sender, EventArgs e)
        {
            string repositoryConnectionString =
                ((ToolStripMenuItem)sender).Tag.ToString();
            ImportTemplate importTemplate =
                new ImportTemplate(repositoryConnectionString);

            importTemplate.ShowDialog();

            // Pick out the selected node.
            XmlNode selectedXmlNode = (XmlNode)trvExplorer.SelectedNode.Tag;

            // Refresh the repository tree.
            XmlDocument repositoryTree =
                MDDEManager.GetRepositoryTreeForSelectedNode(
                repositoryConnectionString, selectedXmlNode);
            RefreshRepositoryForSelectedNode(repositoryTree);
        }

        void refreshInstances_Click(object sender, EventArgs e)
        {
            // Get the repository info.
            string repositoryConnectionString =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).OwnerDocument.
                FirstChild.Attributes["ConnectionString"].Value;

            XmlNode selectedXmlNode = ((XmlNode)((ToolStripMenuItem)sender).Tag).
                SelectSingleNode("//Node[@Type=\"TemplateInstances\"]");

            // Refresh the repository tree.
            if (selectedXmlNode != null)
            {
                XmlDocument repositoryTree =
                    MDDEManager.GetRepositoryTreeForSelectedNode(
                    repositoryConnectionString, selectedXmlNode);
                RefreshRepositoryForSelectedNode(repositoryTree);
            }
        }

        void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Get the repository info.
            string repositoryConnectionString =
                ((ToolStripItem)sender).Tag.ToString();

            // Pick out the selected node.
            XmlNode selectedXmlNode = (XmlNode)trvExplorer.SelectedNode.Tag;

            // Refresh the repository tree.
            XmlDocument repositoryTree =
                MDDEManager.GetRepositoryTreeForSelectedNode(
                repositoryConnectionString, selectedXmlNode);
            RefreshRepositoryForSelectedNode(repositoryTree);
        }

        private void trvExplorer_AfterExpand(
            object sender, TreeViewEventArgs e)
        {
        }

        private void trvExplorer_AfterSelect(
            object sender, TreeViewEventArgs e)
        {
            //MessageBox.Show(e.Node.FullPath);
        }

        private void trvExplorer_MouseUp(object sender, MouseEventArgs e)
        {
            // Show appropriate context menus.
            if (e.Button == MouseButtons.Right)
            {
                // Point where the mouse is clicked.
                Point p = new Point(e.X, e.Y);

                // Get the node that the user has clicked.
                RepositoryTreeNode node =
                    (RepositoryTreeNode)trvExplorer.GetNodeAt(p);
                trvExplorer.SelectedNode = node;

                if (node != null)
                {
                    // Get the data associated.
                    XmlNode data = (XmlNode)node.Tag;

                    switch (data.Attributes["Type"].Value)
                    {
                        case "Templates":
                            DisplayTemplatesContextMenu(sender, p);
                            break;

                        case "Template":
                            DisplayTemplateContextMenu(sender, p);
                            break;

                        case "TemplateInstances":
                            DisplayTemplateInstancesContextMenu(sender, p);
                            break;

                        case "Instance":
                            DisplayTemplateInstanceContextMenu(sender, p);
                            break;

                        case "Packages":
                            DisplayPackagesContextMenu(sender, p);
                            break;

                        case "Package":
                            DisplayPackageContextMenu(sender, p);
                            break;
                    }
                }
            }
        }

        private void updatePackageToolStripMenuItem_Click(
            object sender, EventArgs e)
        {
            string repositoryConnectionString =
               ((XmlNode)((ToolStripMenuItem)sender).Tag).OwnerDocument.
               FirstChild.Attributes["ConnectionString"].Value;

            string packageName =
                ((XmlNode)((ToolStripMenuItem)sender).Tag).
                Attributes["Name"].Value;

            string templateName = ((XmlNode)((ToolStripItem)sender).Tag).
                ParentNode.ParentNode.Attributes["Name"].Value;

            UpdatePackage updatePackage =
                new UpdatePackage(repositoryConnectionString, templateName, packageName);

            updatePackage.ShowDialog();
        }

        #endregion

        #region Helper Methods

        private ToolStripMenuItem AppendMenuItem(ContextMenuStrip ctxMenu,
            string menuItemName, string menuItemText)
        {
            ToolStripMenuItem toolStripMenuItem =
                new ToolStripMenuItem();

            ctxMenu.Items.AddRange(new ToolStripItem[] {
            toolStripMenuItem});

            toolStripMenuItem.Name = menuItemName;

            toolStripMenuItem.Text = menuItemText;

            return toolStripMenuItem;
        }

        private void ConnectToRepository()
        {
            Connect connect = new Connect();
            connect.ShowDialog();
            RefreshRepository(connect.RepositoryTree);
        }

        private void DisplayPackageContextMenu(object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();

            // Add 'Delete package' menu item.
            ToolStripMenuItem deleteToolStripMenuItem =
                AppendMenuItem(
                ctxMenu, "deleteToolStripMenuItem",
                "&Delete");

            deleteToolStripMenuItem.Click +=
                new EventHandler(deleteToolStripMenuItem_Click);

            // Add 'Update package' menu item.
            ToolStripMenuItem updatePackageToolStripMenuItem =
                AppendMenuItem(
                ctxMenu, "updatePackageToolStripMenuItem",
                "&Update");

            updatePackageToolStripMenuItem.Click +=
                new EventHandler(updatePackageToolStripMenuItem_Click);

            // Add 'Export Package' menu item.
            ToolStripMenuItem exportPackageToolStripMenuItem =
                AppendMenuItem(
                ctxMenu, "exportPackageToolStripMenuItem",
                "&Export");

            exportPackageToolStripMenuItem.Click +=
                new EventHandler(exportPackageToolStripMenuItem_Click);

            // Get the node that user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            // Pass on the tagged package information further.
            deleteToolStripMenuItem.Tag =
            updatePackageToolStripMenuItem.Tag =
            exportPackageToolStripMenuItem.Tag = node.Tag;

            ctxMenu.Show((Control)sender, p);
        }

        private void DisplayPackagesContextMenu(object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();

            // Add 'Import package' menu item.
            ToolStripMenuItem importPackageToolStripMenuItem =
                AppendMenuItem(ctxMenu,
                "importPackageToolStripMenuItem", "&Import Package...");

            importPackageToolStripMenuItem.Click +=
                new EventHandler(importPackageToolStripMenuItem_Click);

            // Add 'Refresh' menu item.
            ToolStripMenuItem refreshToolStripMenuItem =
                AppendMenuItem(
                ctxMenu, "refreshToolStripMenuItem", "Re&fresh");

            refreshToolStripMenuItem.Click +=
                new EventHandler(refreshToolStripMenuItem_Click);

            // Get the node that the user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            // Pick out the connection string.
            string repositoryConnectionString =
                ((XmlNode)node.Tag).OwnerDocument.FirstChild.
                Attributes["ConnectionString"].Value;

            // Pass on the tagged information further.
            importPackageToolStripMenuItem.Tag =
                refreshToolStripMenuItem.Tag =
                repositoryConnectionString;

            ctxMenu.Show((Control)sender, p);
        }

        private void DisplayTemplateContextMenu(object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();

            // Add 'Delete' menu item.
            ToolStripMenuItem deleteTemplateMenuItem =
                AppendMenuItem(ctxMenu,
                "deleteTemplateMenuItem", "&Delete");

            deleteTemplateMenuItem.Click +=
                new EventHandler(deleteTemplateMenuItem_Click);

            // Add 'Update' menu item.
            ToolStripMenuItem updateTemplateMenuItem =
                AppendMenuItem(ctxMenu,
                "updateTemplateMenuItem", "&Update");

            updateTemplateMenuItem.Click +=
                new EventHandler(updateTemplateMenuItem_Click);

            // Add 'Upgrade' menu item.
            ToolStripMenuItem upgradeTemplateMenuItem =
                AppendMenuItem(ctxMenu,
                "upgradeTemplateMenuItem", "&Upgrade");

            upgradeTemplateMenuItem.Click +=
                new EventHandler(upgradeTemplateMenuItem_Click);

            // Add 'Generate Packages' menu item.
            ToolStripMenuItem generatePackagesToolStripMenuItem =
                AppendMenuItem(ctxMenu,
                "generatePackagesToolStripMenuItem", "&Generate Packages...");

            generatePackagesToolStripMenuItem.Click +=
                new EventHandler(generatePackagesToolStripMenuItem_Click);

            // Get the node that the user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            deleteTemplateMenuItem.Tag =
            updateTemplateMenuItem.Tag =
            upgradeTemplateMenuItem.Tag =
            generatePackagesToolStripMenuItem.Tag = node.Tag;

            ctxMenu.Show((Control)sender, p);
        }

        private void DisplayTemplateInstanceContextMenu(
            object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();

            // Add the 'Update' menu item.
            ToolStripMenuItem updateInstance =
                AppendMenuItem(ctxMenu,
                "udpateInstance",
                "&Update");

            updateInstance.Click += new EventHandler(updateInstance_Click);

            // Add the 'Delete' menu item.
            ToolStripMenuItem deleteInstance =
                AppendMenuItem(ctxMenu,
                "deleteInstance",
                "&Delete");

            deleteInstance.Click += new EventHandler(deleteInstance_Click);

            // Add the 'Export' menu item.
            ToolStripMenuItem exportInstance =
                AppendMenuItem(ctxMenu,
                "exportInstance",
                "&Export");

            exportInstance.Click += new EventHandler(exportInstance_Click);

            // Get the node that the user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            // Prepare a tag.
            XmlNode xInstance = (XmlNode)node.Tag;
            string[] instanceInfo = new string[3];
            // Add the repository connection string.
            instanceInfo[0] =
                xInstance.OwnerDocument.FirstChild.
                Attributes["ConnectionString"].Value;
            // Add the template name.
            instanceInfo[1] =
                xInstance.ParentNode.ParentNode.Attributes["Name"].Value;
            // Add the instance name.
            instanceInfo[2] =
                xInstance.Attributes["Name"].Value;

            updateInstance.Tag =
                deleteInstance.Tag =
                exportInstance.Tag = instanceInfo;

            ctxMenu.Show((Control)sender, p);
        }

        private void DisplayTemplateInstancesContextMenu(
           object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();

            // Add the 'Create Instance' menu item.
            ToolStripMenuItem createInstanceToolStripMenuItem =
                AppendMenuItem(ctxMenu,
                "createInstanceToolStripMenuItem", "&Create Instance...");

            createInstanceToolStripMenuItem.Click +=
                new EventHandler(createInstanceToolStripMenuItem_Click);

            ToolStripMenuItem createInstanceUsingWizard =
                AppendMenuItem(ctxMenu,
                "createInstanceUsingWizard",
                "&Create Instance Using Wizard...");

            createInstanceUsingWizard.Click +=
                new EventHandler(createInstanceUsingWizard_Click);

            ToolStripMenuItem refreshInstances =
                AppendMenuItem(ctxMenu,
                "refreshInstances",
                "Re&fresh");

            refreshInstances.Click +=
                new EventHandler(refreshInstances_Click);

            // Get the node that the user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            createInstanceToolStripMenuItem.Tag =
                createInstanceUsingWizard.Tag =
                refreshInstances.Tag = node.Parent.Tag;

            ctxMenu.Show((Control)sender, p);
        }

        private void DisplayTemplatesContextMenu(
           object sender, Point p)
        {
            ContextMenuStrip ctxMenu = new ContextMenuStrip();
            ToolStripMenuItem importTemplateToolStripMenuItem =
                new ToolStripMenuItem();

            // Get the node that the user has clicked.
            RepositoryTreeNode node =
                (RepositoryTreeNode)trvExplorer.GetNodeAt(p);

            string repositoryConnectionString =
                ((XmlNode)node.Tag).OwnerDocument.FirstChild.
                Attributes["ConnectionString"].Value;

            ctxMenu.Items.AddRange(new ToolStripItem[] {
            importTemplateToolStripMenuItem});

            importTemplateToolStripMenuItem.Name =
                "importTemplateToolStripMenuItem";
            importTemplateToolStripMenuItem.Text =
                "&Import Template...";
            importTemplateToolStripMenuItem.Click +=
                new EventHandler(importTemplateToolStripMenuItem_Click);
            importTemplateToolStripMenuItem.Tag = repositoryConnectionString;

            ctxMenu.Show((Control)sender, p);
        }

        private void RefreshRepository(XmlDocument repositoryTree)
        {
            // Add the repository to our collection.
            if (repositoryTree != null)
            {
                // Get the repository tree identifier.
                string repositoryIdentifier =
                    repositoryTree.FirstChild.Attributes["Name"].Value;

                // Add repository to our repository collection.
                if (!repositories.ContainsKey(repositoryIdentifier))
                    repositories.Add(
                        repositoryIdentifier, null);

                // // Update the value associated with the repository.
                repositories[repositoryIdentifier] = repositoryTree;

                // Create a new repository node.
                RepositoryTreeNode repositoryNode =
                    new RepositoryTreeNode(
                    repositoryTree.DocumentElement);

                // Create a tree node for this repository.
                if (trvExplorer.Nodes.ContainsKey(repositoryIdentifier))
                {
                    // Save the position of this repository.
                    int index = trvExplorer.Nodes[repositoryIdentifier].Index;

                    // Save the path of the selected node.
                    string fullPath = trvExplorer.SelectedNode.FullPath;

                    // Remove the earlier repository node.
                    trvExplorer.Nodes.RemoveByKey(repositoryIdentifier);

                    // Add the fresh repository information.
                    trvExplorer.Nodes.Insert(index, repositoryNode);

                    // Try to find out the earlier selected node and select it.
                    string[] subPaths = fullPath.Split('\\');
                    TreeNode tn =
                        trvExplorer.Nodes[repositoryIdentifier];
                    for (int i = 1; i < subPaths.Length; i++)
                    {
                        tn.Expand();

                        // Look for the node with the same name.
                        foreach (TreeNode subTn in tn.Nodes)
                            if (subTn.Text == subPaths[i])
                            {
                                tn = subTn;
                                trvExplorer.SelectedNode = tn;
                                break;
                            }
                    }
                }
                else
                {
                    trvExplorer.Nodes.Add(repositoryNode);

                    // Select the repository node.
                    trvExplorer.SelectedNode =
                        trvExplorer.Nodes[repositoryIdentifier];

                    trvExplorer.SelectedNode.Expand();
                }
            }
        }

        private void RefreshRepositoryForSelectedNode(XmlDocument repositoryTree)
        {
            // TODO: Select a node, then remove the node using script from the database.
            // Click refresh. The non-existing node should be removed from the treenode.

            // Add the repository to our collection.
            if (repositoryTree != null)
            {
                // Import the repository tree into the earlier document.
                XmlNode previousInfo = (XmlNode)trvExplorer.SelectedNode.Tag;

                XmlDocument xRepository =
                    previousInfo.OwnerDocument;

                XmlNode newInfo =
                    xRepository.ImportNode(repositoryTree.DocumentElement, true);

                XmlNode xParent = previousInfo.ParentNode;

                xParent.RemoveChild(previousInfo);

                xParent.AppendChild(newInfo);

                // Create a new repository node.
                RepositoryTreeNode repositoryNode =
                    new RepositoryTreeNode(newInfo);

                TreeNode parentNode = trvExplorer.SelectedNode.Parent;
                //Save the position of this repository.                   
                int index = trvExplorer.SelectedNode.Index;

                trvExplorer.SelectedNode.Remove();

                if (parentNode == null)
                    trvExplorer.Nodes.Insert(index, repositoryNode);
                else
                    parentNode.Nodes.Insert(index, repositoryNode);

                repositoryNode.Expand();

                trvExplorer.SelectedNode = repositoryNode;
            }
        }

        #endregion
    }

    internal sealed class RepositoryTreeNode : TreeNode
    {
        internal RepositoryTreeNode(XmlNode data)
        {
            this.Name = this.Text = data.Attributes["Name"].Value;
            this.Tag = data;

            // Create a new repository node per xml node.
            foreach (XmlNode xmlChild in data.ChildNodes)
            {
                RepositoryTreeNode childNode =
                    new RepositoryTreeNode(xmlChild);

                this.Nodes.Add(childNode);
            }
        }
    }
}